package com.tuanzi.loan.web.bean.settlementsystem;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.starbaba.model.utils.JSONUtils;
import com.tuanzi.loan.business.constants.settlement.CompanyCooperationMode;
import com.tuanzi.loan.business.entity.CurrentUser;
import com.tuanzi.loan.business.entity.family.ProductInfo;
import com.tuanzi.loan.business.entity.settlementsystem.*;
import com.tuanzi.loan.business.entity.system.SystemUser;
import com.tuanzi.loan.business.service.settlementsystem.*;
import com.tuanzi.loan.core.aspect.Debug;
import com.tuanzi.loan.vo.request.settlementsystem.SettlementIncomeRequest;
import com.tuanzi.loan.vo.response.settlementsystem.SettlementIncomeResponse;
import com.tuanzi.loan.web.configuration.JSFListingBean;
import com.tuanzi.loan.web.lazy.settlementsystem.SettlementIncomeLazyDataModel;
import com.tuanzi.loan.workflow.service.WorkflowManagerService;
import com.tuanzi.loan.workflow.service.WorkflowProcessorService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.faces.bean.ViewScoped;
import java.util.*;
import java.util.stream.Collectors;

import static com.tuanzi.loan.business.constants.DictionaryCode.*;

/**
 * @author caiwanlin
 * @create 2018-08-16 20:30
 */
@Data
@Debug
@Component
@ViewScoped
@EqualsAndHashCode(callSuper = true)
public class SettlementIncomeListBean extends JSFListingBean<SettlementIncomeRequest,SettlementIncomeResponse> {

    @Autowired
    private SettlementCompanyService settlementCompanyService;

    @Autowired
    private SettlementProductService settlementProductService;

    @Autowired
    private SettlementIncomeService settlementIncomeService;

    @Autowired
    private SettlementIncomeActivityService settlementIncomeActivityService;

    @Autowired
    private SettlementBillService settlementBillService;

    @Autowired
    private WorkflowManagerService workflowManagerService;

    @Autowired
    private WorkflowProcessorService workflowProcessorService;

    private List<SettlementProduct> productList;

    private List<SettlementCompany> companyList;

    private List<ProductInfo> activityList;//活动列表


    private SettlementIncome settlementIncome;//新增消耗记录

    private List<Long> activityIdList; //关联的活动id

    private List<SettlementIncomeResponse> selectIncomeList;//记录选择的消耗记录

    private SettlementBill settlementBill;//开票

    private List<SystemUser> checkList;//财务核查人

    private String PROCESS_DEF_KEY = "BillSystem";//流程定义key

    private boolean hasSeeRight = true;//是否有参看的权限

    private Long onSeeCompanyId; //当前参看公司的ID

    private List<SettlementBillAnnex> billAnnexList;


    private String header = "新增";

    @PostConstruct
    public void init() throws Exception {
        companyList = settlementCompanyService.getCompanyList();
        productList = settlementProductService.getProductList();
        activityList = settlementProductService.getActivityList();
        activityIdList = Lists.newArrayList();
        settlementIncome = new SettlementIncome();
        settlementBill = new SettlementBill();
        billAnnexList = Lists.newArrayList();
        initLazyDataModel();
    }

    private void initLazyDataModel() throws Exception {
        $ = new SettlementIncomeRequest();
        lazyDataModel = new SettlementIncomeLazyDataModel($);
    }

    public void onReset() throws Exception{
        initLazyDataModel();
    }

    public void onBill(){
        //是否选择消耗记录
        if (selectIncomeList == null || selectIncomeList.isEmpty()){
            addErrorMessage("请选择消耗记录");
            return;
        }
        //判断是否存在预付消耗记录
        long count1 = selectIncomeList.parallelStream().filter(s -> {
            return s.getSettlementMode() == 4;
        }).count();
        if (count1 > 0){
            addErrorMessage("请选择结算方式为（后结）的记录");
            return;
        }
        //判断是否选的未开票的记录
        long count = selectIncomeList.parallelStream().filter(s -> {
            return s.getBillStatus() != BillStatus.NO_BILL.index;
        }).count();
        if (count>0){
            addErrorMessage("请选择未开票的记录");
            return;
        }
        //判断是否选择同一主体开票
        Map<Long, List<SettlementIncomeResponse>> collect = selectIncomeList.parallelStream()
                .collect(Collectors.groupingBy(SettlementIncomeResponse::getCompanyId));
        if (collect.size()>1){
            addErrorMessage("请选择同一个主体开票");
            return;
        }
        billAnnexList = Lists.newArrayList();

        //查询主体
        SettlementIncomeResponse settlementIncomeResponse = selectIncomeList.get(0);
        SettlementCompany settlementCompany = settlementCompanyService.findOne(settlementIncomeResponse.getCompanyId());
        //开票金额
        Double incomeAmount = selectIncomeList.parallelStream().map(s -> s.getIncomeAmount()).collect(Collectors.summingDouble(s->s));

        //构造发票实体
        settlementBill = settlementBillService.structureSettlementBill(settlementCompany);
        settlementBill.setBillAmount(incomeAmount);
        //记录类型(消耗)
        settlementBill.setRecordType(RemainType.EXPEND.index);

        checkList = workflowManagerService.findFirstActivitySystemUserProcDefKey(PROCESS_DEF_KEY);
        execute("PF('billing').show();");
        update("incomeForm:bill-dialog");
    }

    public void onSaveBill(){
        String result = settlementBillService.validateBill(settlementBill);
        if (StringUtils.isNotBlank(result)) {
            addErrorMessage(result);
            return;
        }

        //保存
        String checkName = checkList.parallelStream().filter(s -> s.getAccount().equals(settlementBill.getCheckAccount()))
                .map(s -> s.getName()).findFirst().get();

        settlementBill.setCheckName(checkName);//审核人姓名
        List<Long> ids = selectIncomeList.parallelStream().map(s -> (Long) s.getId()).collect(Collectors.toList());
        settlementBill.setDetailList(JSONUtils.toJsonString(selectIncomeList));//保存此时刻的明细快照
        settlementBillService.onSave(settlementBill,ids,billAnnexList);
        selectIncomeList = Lists.newArrayList();

        //启动流程
        String account = CurrentUser.get().getAccount();
        String assignee = settlementBill.getCheckAccount();
        String title = "【"+settlementBill.getCompanyName()+"】消耗开票流程";
        List<String> businessKeys = Lists.newArrayList(settlementBill.getId().toString());
        Map<String, Object> variables = Maps.newHashMap();
        workflowProcessorService.startProcess(account,assignee,PROCESS_DEF_KEY,title,businessKeys,variables);

        addSuccessfullyMessage();
        execute("PF('billing').hide();");
        update("incomeForm");
    }

    /**
     * 消耗记录上传附件
     * @param event
     */
    public void handleAnnexUpload(FileUploadEvent event){
        SettlementBillAnnex annex = new SettlementBillAnnex();
        UploadedFile file = event.getFile();
        String fileName = file.getFileName();
        annex.setName(fileName);
        annex.setCreator(CurrentUser.get().getName());
        annex.setCreateTime(new Date());
        annex.setFileType(fileName.substring(fileName.lastIndexOf(".")+1));
        String url = this.uploadImg(file);
        annex.setUrl(url);
        billAnnexList.add(annex);

        execute("PF('billAnnex').hide();");
        update("incomeForm:bill-dialog");
    }

    /**
     * 删除附件
     */
    public void onDeleteAnnex(Integer index){
        billAnnexList.remove(billAnnexList.get(index));
        update("incomeForm:bill-dialog");
    }

    /**
     * 选择产品回显数据
     */
    public void onSelectProduct(){
        Long productId = settlementIncome.getProductId();
        if (productId == null) {
            settlementIncome = new SettlementIncome();
            activityIdList = Lists.newArrayList();
            return;
        }
        SettlementProduct settlementProduct = settlementProductService.findOne(productId);
        convertIncome(settlementProduct);
    }
    private void convertIncome(SettlementProduct settlementProduct){
        settlementIncome = new SettlementIncome();
        settlementIncome.setProductId(settlementProduct.getId());
        settlementIncome.setProductName(settlementProduct.getProductName());
        settlementIncome.setSpreadMode(settlementProduct.getSpreadMode());
        settlementIncome.setSpreadChannel(settlementProduct.getSpreadChannel());
        settlementIncome.setCopMode(settlementProduct.getCopMode());
        settlementIncome.setIncomeType(settlementProduct.getIncomeType());
        settlementIncome.setPriceCpa(settlementProduct.getPriceCpa());
        settlementIncome.setPriceCps(settlementProduct.getPriceCps());
        settlementIncome.setSettlementMode(settlementProduct.getSettlementMode());
        //关联活动回显
        String activityIdStr = settlementProduct.getActivityIdStr();
        if (StringUtils.isNotBlank(activityIdStr)){
            String[] split = activityIdStr.split(",");
            activityIdList = Arrays.asList(split).stream().map(Long::parseLong).collect(Collectors.toList());
        }
    }

    /**
     * 保存记录
     */
    public void onSave(){
        boolean validate = validate();
        if (validate == false) return;

        //根据合作模式清除不需要的数据
        Integer copMode = settlementIncome.getCopMode();
        clearNotUserData(copMode);

        //获取公司名称
       /* String companyName = companyList.parallelStream().filter(c -> {
            if (c.getId() == settlementIncome.getCompanyId()) return true;
            return false;
        }).map(s -> s.getCompanyName()).findFirst().get();*/
        SettlementCompany con = settlementCompanyService.findOne(settlementIncome.getCompanyId());
        if (con == null){
            addErrorMessage("查询不到公司");
            return;
        }
        String companyName = con.getCompanyName();

        settlementIncome.setCompanyName(companyName);
        settlementIncomeService.onSave(settlementIncome,activityList,activityIdList,onSeeCompanyId);
        addSuccessfullyMessage();
        execute("PF('adding').hide();");
        update("incomeForm");
    }

    public boolean validate(){
        if (settlementIncome.getProductId() == null){
            addErrorMessage("没有选择产品");
            return false;
        }
        if (settlementIncome.getCompanyId() == null){
            addErrorMessage("没有选择主体");
            return false;
        }
        if (settlementIncome.getCopMode() == null){
            addErrorMessage("没有选择合作模式");
            return false;
        }
        if (settlementIncome.getSpreadMode() == null){
            addErrorMessage("没有选择推广方式");
            return false;
        }
        if (settlementIncome.getSpreadChannel() == null){
            addErrorMessage("没有选择推广渠道");
            return false;
        }
        if (settlementIncome.getSettlementMode() == null){
            addErrorMessage("没有选择结算模式");
            return false;
        }
        if (settlementIncome.getIncomeType() == null){
            addErrorMessage("没有选择收入类型");
            return false;
        }
        if (settlementIncome.getStartTime() == null){
            addErrorMessage("没有选择开始日期");
            return false;
        }
        if (settlementIncome.getEndTime() == null){
            addErrorMessage("没有选择结束日期");
            return false;
        }

        if (settlementIncome.getStartTime().compareTo(settlementIncome.getEndTime())>0){
            addErrorMessage("起始日期大于结束日期");
            return false;
        }

        if (settlementIncome.getIncomeAmount() == null){
            addErrorMessage("结算金额为空");
            return false;
        }
        if (activityIdList == null || activityIdList.isEmpty()){
            addErrorMessage("没有关联活动");
            return false;
        }
        return true;
    }



    public void onAdd(Long productId){
        header = "新增";
        hasSeeRight = true;
        if (productId == null){//消耗记录 录入 入口
            settlementIncome = new SettlementIncome();
            activityIdList = Lists.newArrayList();
        }
        else if (productId != null){//产品信息录入入口
            settlementIncome = new SettlementIncome();
            SettlementProduct product = settlementProductService.findOne(productId);
            convertIncome(product);
           /* settlementIncome.setProductId(product.getId());
            settlementIncome.setProductName(product.getProductName());
            settlementIncome.setCopMode(product.getCopMode());
            settlementIncome.setSettlementMode(product.getSettlementMode());
            settlementIncome.setIncomeType(product.getIncomeType());
            settlementIncome.setPriceCpa(product.getPriceCpa());
            settlementIncome.setPriceCps(product.getPriceCps());
            settlementIncome.setSpreadChannel(product.getSpreadChannel());
            settlementIncome.setSpreadMode(product.getSpreadMode());
            settlementIncome.setRemark(product.getRemark());
            if (StringUtils.isNotBlank(product.getActivityIdStr())){
                activityIdList =  Arrays.stream(product.getActivityIdStr().split(",")).map(Long::parseLong).collect(Collectors.toList());
            }
            else {
                activityIdList = Lists.newArrayList();
            }*/
        }

    }

    public void onSee(Long id){
        header = "编辑";
        settlementIncome = settlementIncomeService.findOne(id);
        onSeeCompanyId = settlementIncome.getCompanyId();
        String name = CurrentUser.get().getName();
        hasSeeRight = name.equals(settlementIncome.getCreator()) ? true : false;
        List<SettlementIncomeActivity> byIncomeId = settlementIncomeActivityService.findAllByIncomeId(id);
        activityIdList = byIncomeId.stream().map(sa->sa.getActivityId()).collect(Collectors.toList());
    }

    /**
     * 改变合作模式监听
     */
    public void onChangeCopMode(){
        convertSelectActivityIds();
    }

    /**
     * 监听结算金额
     */
    public void onChangeIncomeAmount(){
        Integer copMode = settlementIncome.getCopMode();
        if (copMode == null) {
            return;
        }
        Double priceCpa = settlementIncome.getPriceCpa();
        Double priceCps = settlementIncome.getPriceCps();
        Integer registerCount = settlementIncome.getRegisterCount();
        Double lendAmount = settlementIncome.getLendAmount();
        Integer clickCount = settlementIncome.getClickCount();
        if (copMode == CompanyCooperationMode.CPA.index){
            if (priceCpa != null && registerCount != null){
                settlementIncome.setIncomeAmount(priceCpa*registerCount);
            }
            else {
                settlementIncome.setIncomeAmount(null);
            }
        }
        else if (copMode == CompanyCooperationMode.CPS.index){
            if (priceCps != null && lendAmount != null){
                settlementIncome.setIncomeAmount((priceCps*lendAmount)/100);
            }
            else {
                settlementIncome.setIncomeAmount(null);
            }
        }
        else if (copMode == CompanyCooperationMode.CPC.index){
            if (priceCpa != null && clickCount != null){
                settlementIncome.setIncomeAmount(priceCpa*clickCount);
            }
            else {
                settlementIncome.setIncomeAmount(null);
            }
        }
        else if (copMode == CompanyCooperationMode.CPA_CPS.index){
            if (priceCpa != null && priceCps != null && registerCount != null && lendAmount != null){
                settlementIncome.setIncomeAmount((priceCpa*registerCount)+(priceCps*lendAmount/100));
            }
            else {
                settlementIncome.setIncomeAmount(null);
            }
        }
    }

    public void onChangeParticipateUv(){
        Date startTime = settlementIncome.getStartTime();
        Date endTime = settlementIncome.getEndTime();
        if (startTime == null || endTime == null) return;
        if (activityIdList == null || activityIdList.isEmpty()) return;
        if (startTime.compareTo(endTime)>0){
            addErrorMessage("起始日期大于结束日期");
            return;
        }
        /*Integer uv = settlementIncomeActivityService.getUv(startTime, endTime, activityIdList);
        settlementIncome.setParticipateUv(uv);*/
    }

    /**
     * 根据合作模式清空不需要的数据
     * @param copMode
     */
    public void clearNotUserData(Integer copMode){
        if (copMode == null) {
            convertSelectActivityIds();
            return;
        }
        if (copMode == CompanyCooperationMode.CPA.index){
            settlementIncome.setPriceCps(null);
            settlementIncome.setLendAmount(null);
            settlementIncome.setClickCount(null);
        }
        else if (copMode == CompanyCooperationMode.CPS.index){
            settlementIncome.setPriceCpa(null);
            settlementIncome.setRegisterCount(null);
            settlementIncome.setClickCount(null);
        }
        else if (copMode == CompanyCooperationMode.CPC.index){
            settlementIncome.setPriceCps(null);
            settlementIncome.setRegisterCount(null);
            settlementIncome.setLendAmount(null);
        }
        else if (copMode == CompanyCooperationMode.CPA_CPS.index){
            settlementIncome.setClickCount(null);
        }
    }

    public void convertSelectActivityIds(){
        ArrayList<Long> temp = new ArrayList<>();
        for (Object a : activityIdList) {
            temp.add(Long.parseLong((String) a));
        }
        activityIdList = temp;
    }




    @Override
    protected List<String> getDictionaryCodes() {
        return  Lists.newArrayList(SETTLEMENT_SPREAD_CHANNEL,SETTLEMENT_INCOME_TYPE,
                SETTLEMENT_SPREAD_MODE, COOPERATION_MODE, SETTLEMENT_CYCLE,
                SETTLEMENT_BILLING_CONTENT,SETTLEMENT_BILL_TYPE,SETTLEMENT_RECEIVE_COMPANY,SETTLEMENT_BILL_STATUS);
    }
}
